<template>
  <canvas type="2d" v-if="isUseNewCanvas" class="fui-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart"
    @touchmove="touchMove" @touchend="touchEnd">
  </canvas>
  <canvas v-else class="fui-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove"
    @touchend="touchEnd">
  </canvas>
</template>

<script>
  import WxCanvas from 'js_sdk/echarts/lib/wx-canvas.min'
  import echarts from 'js_sdk/echarts/lib/echarts.min'
  let ctx
  function wrapTouch(event) {
    for (let i = 0; i < event.touches.length; ++i) {
      const touch = event.touches[i];
      touch.offsetX = touch.x;
      touch.offsetY = touch.y;
    }
    return event;
  }
  export default {
    props: {
      canvasId: {
        type: String,
        default: () => {
          return "fui-canvas";
        }
      },
      opts: {
        type: Object
      },
      use2d: {
        type: Boolean,
        value: true
      }
    },
    data() {
      return {
        $curChart: {},
        toHandleList: [],
        isUseNewCanvas: true,
        canvas: null
      }
    },
    watch: {
      "opts.option": {
        deep: true,
        handler(val, oldVal) {
          console.log('option', val)
          if (val) {
            this.setOption(val)
          }
        }
      }
    },
    onReady: function() {
      if (!this.opts) {
        console.warn(
          '组件需绑定 ec 变量，例：<fui-canvas id="mychart-dom-bar" ' +
          'canvas-id="mychart-bar" ec="{{ ec }}"></fui-canvas>'
        );
        return;
      }
      if (!this.opts.lazyLoad) {
        this.init()
      }
    },
    methods: {
      compareVersion(v1, v2) {
        v1 = v1.split(".");
        v2 = v2.split(".");
        const len = Math.max(v1.length, v2.length);
        while (v1.length < len) {
          v1.push("0");
        }
        while (v2.length < len) {
          v2.push("0");
        }
        for (let i = 0; i < len; i++) {
          const num1 = parseInt(v1[i]);
          const num2 = parseInt(v2[i]);
          if (num1 > num2) {
            return 1;
          } else if (num1 < num2) {
            return -1;
          }
        }
        return 0;
      },
      init(callback) {
        const version = uni.getSystemInfoSync().SDKVersion;
        let canUseNewCanvas = this.compareVersion(version, "2.9.0") >= 0;
        if (this.use2d) {
          if (canUseNewCanvas) console.warn("开发者强制使用旧canvas,建议关闭");
          canUseNewCanvas = false;
        }
        this.isUseNewCanvas = canUseNewCanvas && !this.use2d
        if (this.isUseNewCanvas) {
          console.log('微信基础库版本大于2.9.0，开始使用<canvas type="2d"/>');
          // 2.9.0 可以使用 <canvas type="2d"></canvas>
          this.initByNewWay(callback);
        } else {
          const isValid = this.compareVersion(version, "1.9.91") >= 0;
          if (!isValid) {
            console.error(
              "微信基础库版本过低，需大于等于 1.9.91。" +
              "参见：https://github.com/ecomfe/echarts-for-weixin" +
              "#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82"
            );
            return;
          } else {
            console.warn(
              "建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能"
            );
            this.initByOldWay(callback);
          }
        }
      },
      initByOldWay(callback) {
        // 1.9.91 <= version < 2.9.0：原来的方式初始化
        ctx = uni.createCanvasContext(this.canvasId, this)
        const canvas = new WxCanvas(ctx, this.canvasId, false)
        const that = this
        echarts.setCanvasCreator(() => {
          return canvas
        })
        // const canvasDpr = uni.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
        const canvasDpr = 1
        var query = uni.createSelectorQuery().in(this)
        query
          .select('.fui-canvas')
          .boundingClientRect(res => {

            // that.$data.canvas = canvas
            if (typeof callback === 'function') {
              that.$curChart = callback({echarts, canvas, width: res.width, height: res.height, canvasDpr})
            } else if (that.opts) {
              that.initChart({echarts, canvas, width: res.width, height: res.height, canvasDpr})
            } else {
              that.triggerEvent('init', {
                canvas: canvas,
                width: res.width,
                height: res.height,
                devicePixelRatio: canvasDpr // 增加了dpr，可方便外面echarts.init
              });
            }
          })
          .exec();
      },
      initByNewWay(callback) {
        const that = this
        // version >= 2.9.0：使用新的方式初始化
        const query = uni.createSelectorQuery().in(this);
        query
          .select('.fui-canvas')
          .fields({
            node: true,
            size: true
          })
          .exec(res => {
            const canvasNode = res[0].node;
            const canvasDpr = uni.getSystemInfoSync().pixelRatio;
            const canvasWidth = res[0].width;
            const canvasHeight = res[0].height;
            const ctx = canvasNode.getContext("2d");
            const canvas = new WxCanvas(ctx, that.canvasId, true, canvasNode);
            echarts.setCanvas(canvasNode)
            echarts.setCanvasCreator(() => {
              return canvas;
            })
            // that.$data.canvas = canvas
            if (typeof callback === 'function') {
              that.$curChart = callback({echarts, canvas, width: canvasWidth, height: canvasHeight, canvasDpr})
            } else if (that.opts) {
              that.initChart({echarts, canvas, width: canvasWidth, height: canvasHeight, canvasDpr})
            } else {
              that.triggerEvent("init", {
                canvas: canvas,
                width: canvasWidth,
                height: canvasHeight,
                devicePixelRatio: canvasDpr
              });
            }
          });
      },
      setOption(val) {
        if (!this.$curChart || !this.$curChart.setOption) {
          this.toHandleList.push(val)
        } else {
          this.$curChart.setOption(val)
        }
      },
      canvasToTempFilePath(opt) {
        if (this.isUseNewCanvas) {
          // 新版
          const query = uni.createSelectorQuery().in(this);
          query
            .select(".fui-canvas")
            .fields({
              node: true,
              size: true
            })
            .exec(res => {
              const canvasNode = res[0].node;
              opt.canvas = canvasNode;
              uni.canvasToTempFilePath(opt);
            });
        } else {
          // 旧的
          if (!opt.canvasId) {
            opt.canvasId = this.canvasId;
          }
          ctx.draw(true, () => {
            uni.canvasToTempFilePath(opt, this);
          });
        }
      },
      touchStart(e) {
        if (this.opts.stopTouchEvent) {
          e.preventDefault();
          e.stopPropagation();
          return;
        }
        this.$emit("touchstart", e);
        if (this.$curChart && e.touches.length > 0) {
          var touch = e.touches[0];
          var handler = this.$curChart.getZr().handler;
          if (handler) {
            handler.dispatch("mousedown", {
              zrX: touch.x,
              zrY: touch.y
            });
            handler.dispatch("mousemove", {
              zrX: touch.x,
              zrY: touch.y
            });
            handler.processGesture(wrapTouch(e), "start");
          }
        }
      },
      touchMove(e) {
        if (this.opts.stopTouchEvent) {
          e.preventDefault();
          e.stopPropagation();
          return;
        }
        this.$emit("touchmove", e);
        if (this.$curChart && e.touches.length > 0) {
          var touch = e.touches[0];
          var handler = this.$curChart.getZr().handler;
          if (handler) {
            handler.dispatch("mousemove", {
              zrX: touch.x,
              zrY: touch.y
            });
            handler.processGesture(wrapTouch(e), "change");
          }
        }
      },
      touchEnd(e) {
        if (this.opts.stopTouchEvent) {
          e.preventDefault();
          e.stopPropagation();
          return;
        }
        this.$emit("touchend", e);
        if (this.$curChart) {
          const touch = e.changedTouches ? e.changedTouches[0] : {};
          var handler = this.$curChart.getZr().handler;
          if (handler) {
            handler.dispatch("mouseup", {
              zrX: touch.x,
              zrY: touch.y
            });
            handler.dispatch("click", {
              zrX: touch.x,
              zrY: touch.y
            });
            handler.processGesture(wrapTouch(e), "end");
          }
        }
      },
      initChart({canvas, width, height, canvasDpr}) {
        this.$curChart = echarts.init(canvas, null, {
          width: width,
          height: height,
          devicePixelRatio: canvasDpr
        });
        canvas.setChart(this.$curChart)
        this.$curChart.setOption(this.opts.option)
      },
      async destroy() {
        let { canvas } = await this.getCanvas()
        console.log('canvas', this.canvasId, canvas,  this.$curChart)
        
        this.$curChart.dispose(this.$curChart)
      },
      getCanvas() {
        const query = uni.createSelectorQuery().in(this)
        console.log('获取canvas')
        
        return new Promise(next => {
          if (this.isUseNewCanvas) {
            query
              .select('.fui-canvas')
              .fields({
                node: true,
                size: true
              })
              .exec(res => {
                const canvasNode = res[0].node
                const canvasDpr = uni.getSystemInfoSync().pixelRatio
                const canvasWidth = res[0].width
                const canvasHeight = res[0].height
                const ctx = canvasNode.getContext('2d')
                const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode);
                echarts.setCanvas(canvasNode)
                next({ canvas, canvasNode })
              })
          } else {
            ctx = uni.createCanvasContext(this.canvasId, this)
            const canvas = new WxCanvas(ctx, this.canvasId, false)
            echarts.setCanvasCreator(() => {
              return canvas
            })
            // const canvasDpr = uni.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
            const canvasDpr = 1
            query
              .select('.fui-canvas')
              .boundingClientRect(res => {
                next({ canvas })
              })
              .exec()
          }
            
        })
      }
    }
  };
</script>

<style lang="scss">
  .fui-canvas {
    width: 100%;
    height: 100%;
    display: block;
  }
</style>